home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
nhclb120.zoo
/
ftpcli.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-20
|
15KB
|
697 lines
/* FTP client (interactive user) code */
#define LINELEN 128 /* Length of command buffer */
#include <stdio.h>
#ifdef __TURBOC__
#include "fcntl.h"
#endif
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "netuser.h"
#include "icmp.h"
#include "timer.h"
#include "tcp.h"
#include "ftp.h"
#include "session.h"
#include "cmdparse.h"
#include "telnet.h"
#include "iface.h"
#include "ax25.h"
#include "lapb.h"
#include "finger.h"
#include "nr4.h"
#ifdef BSD
char *sprintf();
#endif
static ftpsetup();
/* #ifdef __TURBOC__ */
/* #include <fcntl.h> */
/* #endif */
extern struct session *current;
extern char nospace[];
extern char badhost[];
static char notsess[] = "Not an FTP session!\n";
static char cantwrite[] = "Can't write %s\n";
static char cantread[] = "Can't read %s\n";
static int sndftpmsg();
static void doreply();
static void ftpccs();
static void ftpcds();
int donothing(),doftpcd(),dolist(),doget(),dols(),doput(),dotype(),doabort(),
domkdir(),dormdir();
struct cmds ftpabort[] = {
"", donothing, 0, NULLCHAR, NULLCHAR,
"abort", doabort, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0, "Only valid command is \"abort\"", NULLCHAR,
};
struct cmds ftpcmds[] = {
"", donothing, 0, NULLCHAR, NULLCHAR,
"cd", doftpcd, 2, "cd <directory>", NULLCHAR,
"dir", dolist, 0, NULLCHAR, NULLCHAR,
"list", dolist, 0, NULLCHAR, NULLCHAR,
"get", doget, 2, "get remotefile <localfile>", NULLCHAR,
"ls", dols, 0, NULLCHAR, NULLCHAR,
"mkdir", domkdir, 2, "mkdir <directory>", NULLCHAR,
"nlst", dols, 0, NULLCHAR, NULLCHAR,
"rmdir", dormdir, 2, "rmdir <directory>", NULLCHAR,
"put", doput, 2, "put localfile <remotefile>", NULLCHAR,
"type", dotype, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0, NULLCHAR, NULLCHAR,
};
/* Handle top-level FTP command */
doftp(argc,argv)
int argc;
char *argv[];
{
int32 resolve();
int ftpparse();
char *inet_ntoa();
void ftpccr(),ftpccs();
struct session *s;
struct ftp *ftp,*ftp_create();
struct tcb *tcb;
struct socket lsocket,fsocket;
lsocket.address = ip_addr;
lsocket.port = lport++;
printf("Lookup ... ");
if((fsocket.address = resolve(argv[1])) == 0){
printf(badhost,argv[1]);
return 1;
}
if(argc < 3)
fsocket.port = FTP_PORT;
else
fsocket.port = atoi(argv[2]);
printf(" done. Trying to connect to %s ...\n",
inet_ntoa( fsocket.address));
/* Allocate a session control block */
if((s = newsession()) == NULLSESSION){
printf("Too many sessions\n");
return 1;
}
current = s;
if((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
strcpy(s->name,argv[1]);
s->type = FTP;
s->parse = ftpparse;
/* Allocate an FTP control block */
if((ftp = ftp_create(LINELEN)) == NULLFTP){
s->type = FREE;
printf(nospace);
return 1;
}
ftp->state = STARTUP_STATE;
s->cb.ftp = ftp; /* Downward link */
ftp->session = s; /* Upward link */
/* Now open the control connection */
tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,
0,ftpccr,NULLVFP,ftpccs,0,(char *)ftp);
ftp->control = tcb;
go();
return 0;
}
/* Parse user FTP commands */
int
ftpparse(line,len)
char *line;
int16 len;
{
struct mbuf *bp;
switch(current->cb.ftp->state){
case RECEIVING_STATE:
case SENDING_STATE:
/* The only command allowed in data transfer state is ABORT */
if(cmdparse(ftpabort,line) == -1){
printf("Transfer in progress; only ABORT is acceptable\n");
}
fflush(stdout);
break;
case COMMAND_STATE:
/* Save it now because cmdparse modifies the original */
bp = qdata(line,len);
if(cmdparse(ftpcmds,line) == -1){
/* Send it direct */
if(bp != NULLBUF)
send_tcp(current->cb.ftp->control,bp);
else
printf(nospace);
} else {
free_p(bp);
}
fflush(stdout);
break;
case STARTUP_STATE: /* Starting up autologin */
printf("Not connected yet, ignoring %s\r\n",line);
break;
case USER_STATE: /* Got the user name */
line[len] = '\0';
return sndftpmsg(current->cb.ftp,"USER %s",line);
case PASS_STATE: /* Got the password */
cooked();
line[len] = '\0';
return sndftpmsg(current->cb.ftp,"PASS %s",line);
}
return 0;
}
/* Handle null line to avoid trapping on first command in table */
/*ARGSUSED*/
static
int
donothing(argc,argv)
int argc;
char *argv[];
{
}
/* Translate 'cd' to 'cwd' for convenience */
/*ARGSUSED*/
static
int
doftpcd(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
return sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
}
/* Translate 'mkdir' to 'xmkd' for convenience */
/*ARGSUSED*/
static
int
domkdir(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
return sndftpmsg(ftp,"XMKD %s\r\n",argv[1]);
}
/* Translate 'rmdir' to 'xrmd' for convenience */
/*ARGSUSED*/
static
int
dormdir(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
return sndftpmsg(ftp,"XRMD %s\r\n",argv[1]);
}
/* Handle "type" command from user */
static
int
dotype(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
if(argc < 2){
switch(ftp->type){
case IMAGE_TYPE:
printf("Image\n");
break;
case ASCII_TYPE:
printf("Ascii\n");
break;
}
return 0;
}
switch(*argv[1]){
case 'i':
case 'b':
ftp->type = IMAGE_TYPE;
sndftpmsg(ftp,"TYPE I\r\n");
break;
case 'a':
ftp->type = ASCII_TYPE;
sndftpmsg(ftp,"TYPE A\r\n");
break;
case 'l':
ftp->type = IMAGE_TYPE;
sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
break;
default:
printf("Invalid type %s\n",argv[1]);
return 1;
}
return 0;
}
/* Start receive transfer. Syntax: get <remote name> [<local name>] */
static
doget(argc,argv)
int argc;
char *argv[];
{
void ftpdr(),ftpcds();
char *remotename,*localname;
register struct ftp *ftp;
char *mode;
ftp = current->cb.ftp;
if(ftp == NULLFTP){
printf(notsess);
return 1;
}
remotename = argv[1];
if(argc < 3)
localname = remotename;
else
localname = argv[2];
if(ftp->fp != NULLFILE && ftp->fp != stdout)
fclose(ftp->fp);
ftp->fp = NULLFILE;
if(ftp->type == IMAGE_TYPE)
mode = binmode[WRITE_BINARY];
else
mode = "w";
if((ftp->fp = fopen(localname,mode)) == NULLFILE){
printf(cantwrite,localname);
return 1;
}
ftp->state = RECEIVING_STATE;
ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
/* Generate the command to start the transfer */
return sndftpmsg(ftp,"RETR %s\r\n",remotename);
}
/* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
static
dolist(argc,argv)
int argc;
char *argv[];
{
void ftpdr(),ftpcds();
register struct ftp *ftp;
ftp = current->cb.ftp;
if(ftp == NULLFTP){
printf(notsess);
return 1;
}
if(ftp->fp != NULLFILE && ftp->fp != stdout)
fclose(ftp->fp);
ftp->fp = NULLFILE;
if(argc < 3){
ftp->fp = stdout;
} else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
printf(cantwrite,argv[2]);
return 1;
}
ftp->state = RECEIVING_STATE;
ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
/* Generate the command to start the transfer
* It's done this way to avoid confusing the 4.2 FTP server
* if there's no argument
*/
if(argc > 1)
return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
else
return sndftpmsg(ftp,"LIST\r\n","");
}
/* Abbreviated (name only) list of remote directory.
* Syntax: ls <remote directory/file> [<local name>]
*/
static
dols(argc,argv)
int argc;
char *argv[];
{
void ftpdr(),ftpcds();
register struct ftp *ftp;
ftp = current->cb.ftp;
if(ftp == NULLFTP){
printf(notsess);
return 1;
}
if(ftp->fp != NULLFILE && ftp->fp != stdout)
fclose(ftp->fp);
ftp->fp = NULLFILE;
if(argc < 3){
ftp->fp = stdout;
} else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
printf(cantwrite,argv[2]);
return 1;
}
ftp->state = RECEIVING_STATE;
ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
/* Generate the command to start the transfer */
if(argc > 1)
return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
else
return sndftpmsg(ftp,"NLST\r\n","");
}
/* Start transmit. Syntax: put <local name> [<remote name>] */
static
doput(argc,argv)
int argc;
char *argv[];
{
void ftpdt(),ftpcds();
char *remotename,*localname;
char *mode;
struct ftp *ftp;
if((ftp = current->cb.ftp) == NULLFTP){
printf(notsess);
return 1;
}
localname =